﻿using HT.Future.Common;
using HT.Future.Entities;
using HT.Future.IService;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using OfficeOpenXml;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Transactions;

namespace HT.Future.Service
{
    public class OrganizationService : BaseService<Department>, IOrganizationService
    {
        private ILogger<OrganizationService> _logger;
        public OrganizationService(HtDbContext dbContext, ILogger<OrganizationService> logger) : base(dbContext)
        {
            _logger = logger;
        }

        public async Task ImportOrganizationAsync(Stream stream)
        {
            var orgs = await Table.ToListAsync();
            var company = orgs.FirstOrDefault(a => a.Id == 1);
            if (string.IsNullOrEmpty(company.ObjectId))
            {
                company.ObjectId = "cb9314cf9d874a31b4bf3460d388ec52";
                company.FullObjectId = company.ObjectId;
            }
            company.Departments = company.Departments ?? new List<Department>();

            /**
             * 第三列是单位，第四列是部门
             */
            using (var package = new ExcelPackage(stream))
            {
                var sheet = package.Workbook.Worksheets[1];
                var rowCount = sheet.Dimension.Rows;


                for (int i = 2; i <= rowCount; i++)
                {
                    var unitName = sheet.Cells[i, 3].GetValue<string>();
                    var departmentName = sheet.Cells[i, 4].GetValue<string>();
                    var unitArr = unitName.Split('/');
                    var departmentArr = departmentName.Split('/');
                    var units = unitArr.Concat(departmentArr).Distinct().ToList();
                    units.RemoveAt(0);
                    Department dept = company;
                    units.ForEach(unit =>
                    {
                        dept = CreateDepartment(dept, unit);
                    });
                }
                await DbContext.SaveChangesAsync();
            }

            Department CreateDepartment(Department parent, string unit)
            {
                var dept = parent.Departments.FirstOrDefault(a => a.Name == unit);
                if (dept != null) return dept;
                var objectId = Guid.NewGuid().ToString().Replace("-", "").ToLower();
                dept = new Department { ParentId = parent.Id, Sort = parent.Departments.Count + 1, FullName = $"{parent.FullName}/{unit}", Name = unit, Departments = new List<Department>(), Level = parent.Level + 1, ObjectId = objectId, FullObjectId = $"{parent.FullObjectId}.{objectId}" };

                parent.Departments.Add(dept);
                return dept;
            }
        }

        public async Task ImportUserAsync(Stream stream)
        {
            var orgs = await Table.ToListAsync();
            var pwd = "000000".ToMd5();

            /**
             * 第二列是姓名
             * 第三列是单位
             * 第四列是部门
             * 第五列是岗位
             * 第六列是手机号
             * 第七列是性别
             * 第八列是员工类别
             * 第九列是职称
             */
            using (var package = new ExcelPackage(stream))
            {
                var sheet = package.Workbook.Worksheets[1];
                var rowCount = sheet.Dimension.Rows;
                var now = DateTime.Now;
                var sort = 1;       // 排序码

                for (int i = 2; i <= rowCount; i++)
                {
                    var unitName = sheet.Cells[i, 3].GetValue<string>();
                    var departmentName = sheet.Cells[i, 4].GetValue<string>();
                    var unitArr = unitName.Split('/');
                    var departmentArr = departmentName.Split('/');
                    var units = unitArr.Concat(departmentArr).Distinct().ToList();
                    var departmentFullName = string.Join("/", units);

                    var department = orgs.First(a => a.FullName == departmentFullName);     // 找到用户部门
                    var fullname = sheet.Cells[i, 2].GetValue<string>();                    // 用户全名
                    var phone = sheet.Cells[i, 6].GetValue<string>();                       // 用户手机号

                    if (department.Users != null && department.Users.Any(a => a.FullName == fullname && a.PhoneNumber == phone)) continue;      // 如果部门下存在用户，则不添加

                    var gender = sheet.Cells[i, 7].GetValue<string>() == "男" ? GenderType.Male : GenderType.Female;
                    var type = GetType(sheet.Cells[i, 8].GetValue<string>());
                    var title = sheet.Cells[i, 9].GetValue<string>();
                    var post = sheet.Cells[i, 5].GetValue<string>();
                    var user = new User
                    {
                        FullName = fullname,
                        DepartmentId = department.Id,
                        DepartmentObjectFullId = department.FullObjectId,
                        UserName = phone,
                        PhoneNumber = phone,
                        Password = pwd,
                        Gender = gender,
                        CreateTime = now,
                        IsActive = true,
                        UserType = type,
                        Title = title,
                        Sort = sort++,
                        PostName = post
                    };
                    await DbContext.AddAsync(user);
                }
                await DbContext.SaveChangesAsync();
            }


            UserType GetType(string type)
            {
                if (type == "在编") return UserType.A;
                if (type == "聘用") return UserType.B;
                return UserType.C;
            }
        }

        public async Task<Department> GetChildsAsync(int id)
        {
            return await Table
                .Include(a => a.Departments)
                .ThenInclude(a => a.Departments)
                //.Include(a => a.Users)
                .FirstOrDefaultAsync(a => a.Id == id);
        }

        public async Task<List<User>> GetChildUsersAsync(int id)
        {
            var dept = await GetByIdAsync(id);
            return await DbContext.Set<User>()
                .AsNoTracking()
                .Where(a => a.DepartmentObjectFullId.Contains(dept.ObjectId))
                .OrderBy(a => a.Sort)
                .ToListAsync();
        }

        public async Task<byte[]> GetDepartmentUsersToExcelAsync(int id)
        {
            var dept = await GetByIdAsync(id);
            var list = await DbContext.Set<User>()
                .AsNoTracking()
                .Include(a => a.Department)
                .Where(a => a.DepartmentObjectFullId.Contains(dept.ObjectId))
                .OrderBy(a => a.Sort)
                .ToListAsync();
            using (var package = new ExcelPackage())
            {
                var worksheet = package.Workbook.Worksheets.Add(dept.Name);

                worksheet.Cells[1, 1].Value = "序号";
                worksheet.Cells[1, 2].Value = "科室";
                worksheet.Cells[1, 3].Value = "专业";
                worksheet.Cells[1, 4].Value = "职务";
                worksheet.Cells[1, 5].Value = "姓名";
                worksheet.Cells[1, 6].Value = "岗位类型";
                worksheet.Cells[1, 7].Value = "员工类别";
                worksheet.Cells[1, 8].Value = "有无OA帐号";
                worksheet.Cells[1, 9].Value = "性别";
                worksheet.Cells[1, 10].Value = "出生日期";
                worksheet.Cells[1, 11].Value = "毕业日期";
                worksheet.Cells[1, 12].Value = "毕业学校";
                worksheet.Cells[1, 13].Value = "来院日期";
                worksheet.Cells[1, 14].Value = "职称";
                worksheet.Cells[1, 15].Value = "职称取得日期";
                worksheet.Cells[1, 16].Value = "手机号";
                worksheet.Cells[1, 17].Value = "固定电话";
                worksheet.Cells[1, 18].Value = "办公室";
                worksheet.Cells[1, 19].Value = "单位名称";

                worksheet.Cells[2, 2].Value = "要与组织架构里面保持一致，最好是把各单位的组织架构发给各单位对照填写";
                worksheet.Cells[2, 3].Value = "要标准化，与系统里面各单位的专业对应上，便于导入";
                worksheet.Cells[2, 7].Value = @"标准化
在编
B类
C类";

                var rowIndex = 3;
                list.ForEach(item =>
                {
                    worksheet.Cells[rowIndex, 1].Value = rowIndex - 2;
                    worksheet.Cells[rowIndex, 2].Value = item.Department.Name;
                    worksheet.Cells[rowIndex, 4].Value = item.PostName;
                    worksheet.Cells[rowIndex, 5].Value = item.FullName;
                    worksheet.Cells[rowIndex, 7].Value = item.UserType.ToDisplay();
                    worksheet.Cells[rowIndex, 9].Value = item.Gender.ToDisplay();
                    worksheet.Cells[rowIndex, 16].Value = item.PhoneNumber;
                    worksheet.Cells[rowIndex, 19].Value = dept.Name;
                    rowIndex++;
                });
                return package.GetAsByteArray();
            }
        }

        public async Task<Department> UpdateAsync(Department department)
        {
            var entity = await Table.Include(a => a.Parent).FirstOrDefaultAsync(a => a.Id == department.Id);
            entity.Name = department.Name;
            entity.ModifyTime = DateTime.Now;
            if (entity.Parent != null)
            {
                entity.FullName = $"{entity.Parent.FullName}/{entity.Name}";
            }
            else
            {
                entity.FullName = entity.Name;
            }
            entity.Sort = department.Sort;
            entity.Description = department.Description;
            await DbContext.SaveChangesAsync();
            return entity;
        }

        public async Task<Department> CreateDepartmentAsync(Department department)
        {
            var parent = await TableNoTracking.FirstAsync(a => a.Id == department.ParentId);
            department.FullName = $"{parent.FullName}/{department.Name}";
            department.Level = parent.Level + 1;
            department.CreateTime = DateTime.Now;
            await AddAsync(department);
            return department;
        }

        public async Task<int> ChildrenMaxSortAsync(int id)
        {
            return await TableNoTracking.MaxAsync(a => a.Sort);
        }

        public async Task<byte[]> GetOrganizationExcelAsync()
        {
            var list = await Table.OrderBy(a => a.Sort).ToListAsync();
            var company = list.First(a => a.Id == 1);
            var rowIndex = 2;
            using (var package = new ExcelPackage())
            {
                var worksheet = package.Workbook.Worksheets.Add("组织架构");

                var maxLevel = list.Max(a => a.Level);
                var levelStr = new[] { "一", "二", "三", "四", "五", "六" };
                for (int i = 1; i <= maxLevel; i++)
                {
                    worksheet.Cells[1, i].Value = $"{levelStr[i - 1]}级部门";
                }

                LoadDepartment(company, 1);

                return package.GetAsByteArray();




                void LoadDepartment(Department dept, int level)
                {
                    int curRow = rowIndex;
                    worksheet.Cells[curRow, level].Value = dept.Name;
                    if (dept.Departments != null && dept.Departments.Count > 0)
                    {
                        dept.Departments.ForEach(a => LoadDepartment(a, level + 1));
                        worksheet.Cells[curRow, level, rowIndex - 1, level].Merge = true;
                    }
                    else
                    {
                        rowIndex++;
                    }
                }

            }
        }

        public async Task<byte[]> GetAllUsersToExcelAsync()
        {
            var users = await DbContext.Set<User>()
                .AsNoTracking()
                .Include(a => a.Department)
                .OrderBy(a => a.Sort)
                .Where(a => a.Id != 1)
                .ToListAsync();

            using (var package = new ExcelPackage())
            {
                var worksheet = package.Workbook.Worksheets.Add("Sheet1");

                worksheet.Cells[1, 1].Value = "姓名";
                worksheet.Cells[1, 2].Value = "帐号";
                worksheet.Cells[1, 3].Value = "别名";
                worksheet.Cells[1, 4].Value = "职务";
                worksheet.Cells[1, 5].Value = "部门";
                worksheet.Cells[1, 6].Value = "性别";
                worksheet.Cells[1, 7].Value = "手机";
                worksheet.Cells[1, 8].Value = "座机";
                worksheet.Cells[1, 9].Value = "部门";
                worksheet.Cells[1, 10].Value = "个人邮箱";
                worksheet.Cells[1, 11].Value = "地址";
                worksheet.Cells[1, 12].Value = "企业简称";
                worksheet.Cells[1, 13].Value = "英文名";
                worksheet.Cells[1, 14].Value = "激活状态";
                worksheet.Cells[1, 15].Value = "禁用状态";
                worksheet.Cells[1, 16].Value = "微信插件";

                var rowIndex = 2;
                users.ForEach(item =>
                {
                    worksheet.Cells[rowIndex, 1].Value = item.FullName;
                    worksheet.Cells[rowIndex, 2].Value = item.UserName;
                    worksheet.Cells[rowIndex, 4].Value = item.PostName;
                    worksheet.Cells[rowIndex, 5].Value = item.Department.FullName;
                    worksheet.Cells[rowIndex, 6].Value = item.Gender.ToDisplay();
                    worksheet.Cells[rowIndex, 7].Value = item.PhoneNumber;
                    rowIndex++;
                });
                return package.GetAsByteArray();
            }
        }

        public async Task<int> GetUserQuantityOfDepartment(string objectId)
        {
            return await DbContext.Set<User>()
                .AsNoTracking()
                .Where(a => a.DepartmentObjectFullId.Contains(objectId))
                .CountAsync();
        }

    }
}
